import os
import re
import sys
from enum import Enum, auto
from xml.etree import ElementTree

option_dict_dir = os.path.join(os.path.dirname(__file__), os.path.join("clang_option_dict", "clang_option_xml"))
# the option dict config should place in "./gcc_option_dict/" directory, name style like "ver.xml"
option_dict_config_file_template = os.path.join(option_dict_dir, "{}.xml")

def custom_sort(ver):
    parts = ver.split(".")
    parts = [int(part) for part in parts]
    return parts

def custom_cmp(ver1, ver2):
    parts1 = ver1.split(".")
    parts1 = [int(part) for part in parts1]
    
    parts2 = ver2.split(".")
    parts2 = [int(part) for part in parts2]
    
    for idx in range(len(parts1)):
        if parts1[idx] > parts2[idx]:
            return 1
        elif parts1[idx] > parts2[idx]:
            return -1
        else:
            continue
    return 0


class OptionCategory(Enum):
    
    OVERALL = 1
    COMPILE = auto()
    WARNING = auto()
    DEBUGGING = auto()
    OPTIMIZATION = auto()
    LINKER = auto()
    FORTRAN = auto()
    NONETIME = auto()
    UNSUPPORTED = auto()
    SOURCE_FILE = auto()
    UNKNOWN = auto()


class OptionDictFactory(object):
    
    def get_option_dict_by_ver(ver=""):
        
        config_file = option_dict_config_file_template.format(ver)
        
        if not os.path.exists(config_file):
            # we need to select to nearest option dict config file 
            ver = OptionDictFactory.ver_match(ver)

        config_file = option_dict_config_file_template.format(ver)
        return OptionDict(config_file=config_file)
    
    def ver_match(ver=""):
        curver = ver
        verlist = sorted([os.path.splitext(file)[0] for file in os.listdir(option_dict_dir) if file.endswith(".xml")], key=custom_sort)
        idx = 0
        while idx < len(verlist):
            if custom_cmp(curver, verlist[idx]) <= 0:
                break
            idx += 1
        if idx >= len(verlist):
            result = verlist[-1]
        else:
            result = verlist[idx]
        
        return result
    

class OptionDict(object):
    
    def __init__(self, config_file=""):
        
        if not os.path.exists(config_file):
            raise Exception("There is not correspond configure file %s" % config_file)
        
        self.simple_option_dict = {}
        self.space_option_dict = {}
        self.equal_option_dict = {}
        self.match_option_dict = {}
        
        self.__load_option_dict(config_file)
        
    def __load_option_dict(self, config_file=""):
        
        option_dict_map = {
            "simple": self.simple_option_dict,
            "space": self.space_option_dict,
            "equal": self.equal_option_dict,
            "match": self.match_option_dict
        }
        
        category_map = {
            "overall" : OptionCategory.OVERALL,
            "compile" : OptionCategory.COMPILE,
            "warning" : OptionCategory.WARNING,
            "debugging" : OptionCategory.DEBUGGING,
            "optimization" : OptionCategory.OPTIMIZATION,
            "linker" : OptionCategory.LINKER,
            "fortran": OptionCategory.FORTRAN,
            "nonetime": OptionCategory.NONETIME,
            "unsupported": OptionCategory.UNSUPPORTED,
        }
        
        dict_tree = ElementTree.parse(config_file)
        root = dict_tree.getroot()
        for kind in root:
            for option in kind:
                option_dict = option_dict_map.get(kind.tag)
                category = category_map.get(option.tag, None)
                if not category:
                    print(option.tag)
                self.__append_simple_option(option.text, category, option_dict)
    
                
    def __append_simple_option(self, option="", category="", option_dict=""):
        
        item = {
            "category" : category,
            "support" : True if category != OptionCategory.UNSUPPORTED else False
        }
        option_dict[option] = item
    
    
    def get_simple_dict(self):
        return self.simple_option_dict

    
    def get_space_dict(self):
        return self.space_option_dict
    
    
    def get_equal_dict(self):
        return self.equal_option_dict
    
    
    def get_match_dict(self):
        return self.match_option_dict
        
        

if __name__ == "__main__":
    ver_list = [file.rsplit('.', 1)[0] for file in os.listdir(option_dict_dir) if file.endswith(".xml")]
    for ver in ver_list:
        obj = OptionDictFactory.get_option_dict_by_ver(ver)
        
        